/*
 * periodic.c
 *
 * Copyright 2011 Pieter Agten
 *
 * This file is part of Yarf.
 *
 * Yarf is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Yarf is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Yarf.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file   periodic.c
 * @author Pieter Agten (pieter.agten@gmail.com)
 * @date   30 okt 2011
 * @brief  The periodic scheduler allows tasks to be executed at periodic 
 *         intervals.
 */


#include "periodic.h"
#include "periodic_notify.h"

#include "util/math.h"

#include <stdio.h>


/**
 * Pointer to the head of the linked list of periodic tasks to execute.
 */
static periodic_task_t *tasks;


void 
periodic_init(void)
{
  tasks = NULL;
}


void
periodic_task_set(periodic_task_t *task, void (*f)(void), unsigned long ms)
{
  task->f = f;
  task->ms_periodic = MAX(ms,1);
  task->ms_remaining = task->ms_periodic;
  task->next = NULL;
}

void
periodic_add(periodic_task_t *task)
{
  periodic_task_t **tp = &tasks;
  while (*tp != NULL) {
    tp = &((*tp)->next);
  }
  *tp = task;
}

void
periodic_remove(periodic_task_t *task)
{
  periodic_task_t **tp = &tasks;
  while (*tp != NULL && *tp != task) {
    tp = &((*tp)->next);
  }

  if (*tp == task) {
    *tp = (*tp)->next;
  }
}

void 
periodic_notify_ms(void)
{
  periodic_task_t *task = tasks;
  while (task != NULL) {
    task->ms_remaining -= 1;
    if (task->ms_remaining == 0) {
      task->ms_remaining = task->ms_periodic;
      task->f();
    }
    task = task->next;
  }
}


